home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 24
/
Amiga Format AFCD24 (Feb 1998, Issue 108).iso
/
-in_the_mag-
/
emulation
/
uae
/
uae-0.4.3
/
memory.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-20
|
9KB
|
366 lines
/*
* UAE - The Un*x Amiga Emulator
*
* Memory management
*
* (c) 1995 Bernd Schmidt
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "config.h"
#include "amiga.h"
#include "options.h"
#include "memory.h"
#include "custom.h"
#include "cia.h"
#include "ersatz.h"
bool buserr;
lget_func do_lget[256];
wget_func do_wget[256];
bget_func do_bget[256];
lput_func do_lput[256];
wput_func do_wput[256];
bput_func do_bput[256];
xlate_func do_xlateaddr[256];
check_func do_check[256];
/* Default memory access functions */
bool default_check(CPTR a, ULONG b)
{
return false;
}
UWORD *default_xlate(CPTR a)
{
fprintf(stderr, "Your Amiga program just did something terribly stupid\n");
return 0;
}
/* Chip memory */
static UWORD chipmemory[chipmem_size/2];
static ULONG chipmem_lget(CPTR) REGPARAM;
static UWORD chipmem_wget(CPTR) REGPARAM;
static UBYTE chipmem_bget(CPTR) REGPARAM;
static void chipmem_lput(CPTR, ULONG) REGPARAM;
static void chipmem_wput(CPTR, UWORD) REGPARAM;
static void chipmem_bput(CPTR, UBYTE) REGPARAM;
static bool chipmem_check(CPTR addr, ULONG size) REGPARAM;
static UWORD *chipmem_xlate(CPTR addr) REGPARAM;
ULONG chipmem_lget(CPTR addr)
{
addr -= chipmem_start & (chipmem_size-1);
addr &= chipmem_size-1;
return ((ULONG)chipmemory[addr >> 1] << 16) | chipmemory[(addr >> 1)+1];
}
UWORD chipmem_wget(CPTR addr)
{
addr -= chipmem_start & (chipmem_size-1);
addr &= chipmem_size-1;
return chipmemory[addr >> 1];
}
UBYTE chipmem_bget(CPTR addr)
{
addr -= chipmem_start & (chipmem_size-1);
addr &= chipmem_size-1;
return chipmemory[addr >> 1] >> (addr & 1 ? 0 : 8);
}
void chipmem_lput(CPTR addr, ULONG l)
{
addr -= chipmem_start & (chipmem_size-1);
addr &= chipmem_size-1;
chipmemory[addr >> 1] = l >> 16;
chipmemory[(addr >> 1)+1] = (UWORD)l;
}
void chipmem_wput(CPTR addr, UWORD w)
{
addr -= chipmem_start & (chipmem_size-1);
addr &= chipmem_size-1;
chipmemory[addr >> 1] = w;
}
void chipmem_bput(CPTR addr, UBYTE b)
{
addr -= chipmem_start & (chipmem_size-1);
addr &= chipmem_size-1;
if (!(addr & 1)) {
chipmemory[addr>>1] = (chipmemory[addr>>1] & 0xff) | (((UWORD)b) << 8);
} else {
chipmemory[addr>>1] = (chipmemory[addr>>1] & 0xff00) | b;
}
}
bool chipmem_check(CPTR addr, ULONG size)
{
addr -= chipmem_start & (chipmem_size-1);
addr &= chipmem_size-1;
return (addr + size) < chipmem_size;
}
UWORD *chipmem_xlate(CPTR addr)
{
addr -= chipmem_start & (chipmem_size-1);
addr &= chipmem_size-1;
return chipmemory + (addr >> 1);
}
/* Slow memory */
static UWORD *bogomemory;
static ULONG bogomem_lget(CPTR) REGPARAM;
static UWORD bogomem_wget(CPTR) REGPARAM;
static UBYTE bogomem_bget(CPTR) REGPARAM;
static void bogomem_lput(CPTR, ULONG) REGPARAM;
static void bogomem_wput(CPTR, UWORD) REGPARAM;
static void bogomem_bput(CPTR, UBYTE) REGPARAM;
static bool bogomem_check(CPTR addr, ULONG size) REGPARAM;
static UWORD *bogomem_xlate(CPTR addr) REGPARAM;
ULONG bogomem_lget(CPTR addr)
{
addr -= bogomem_start & (bogomem_size-1);
addr &= bogomem_size-1;
return ((ULONG)bogomemory[addr >> 1] << 16) | bogomemory[(addr >> 1)+1];
}
UWORD bogomem_wget(CPTR addr)
{
addr -= bogomem_start & (bogomem_size-1);
addr &= bogomem_size-1;
return bogomemory[addr >> 1];
}
UBYTE bogomem_bget(CPTR addr)
{
addr -= bogomem_start & (bogomem_size-1);
addr &= bogomem_size-1;
return bogomemory[addr >> 1] >> (addr & 1 ? 0 : 8);
}
void bogomem_lput(CPTR addr, ULONG l)
{
addr -= bogomem_start & (bogomem_size-1);
addr &= bogomem_size-1;
bogomemory[addr >> 1] = l >> 16;
bogomemory[(addr >> 1)+1] = (UWORD)l;
}
void bogomem_wput(CPTR addr, UWORD w)
{
addr -= bogomem_start & (bogomem_size-1);
addr &= bogomem_size-1;
bogomemory[addr >> 1] = w;
}
void bogomem_bput(CPTR addr, UBYTE b)
{
addr -= bogomem_start & (bogomem_size-1);
addr &= bogomem_size-1;
if (!(addr & 1)) {
bogomemory[addr>>1] = (bogomemory[addr>>1] & 0xff) | (((UWORD)b) << 8);
} else {
bogomemory[addr>>1] = (bogomemory[addr>>1] & 0xff00) | b;
}
}
bool bogomem_check(CPTR addr, ULONG size)
{
addr -= bogomem_start & (bogomem_size-1);
addr &= bogomem_size-1;
return (addr + size) < bogomem_size;
}
UWORD *bogomem_xlate(CPTR addr)
{
addr -= bogomem_start & (bogomem_size-1);
addr &= bogomem_size-1;
return bogomemory + (addr >> 1);
}
/* Kick memory */
static int zkickfile = 0;
static UWORD kickmemory[kickmem_size/2];
static ULONG kickmem_lget(CPTR) REGPARAM;
static UWORD kickmem_wget(CPTR) REGPARAM;
static UBYTE kickmem_bget(CPTR) REGPARAM;
static void kickmem_lput(CPTR, ULONG) REGPARAM;
static void kickmem_wput(CPTR, UWORD) REGPARAM;
static void kickmem_bput(CPTR, UBYTE) REGPARAM;
static bool kickmem_check(CPTR addr, ULONG size) REGPARAM;
static UWORD *kickmem_xlate(CPTR addr) REGPARAM;
ULONG kickmem_lget(CPTR addr)
{
addr -= kickmem_start & (kickmem_size-1);
addr &= kickmem_size-1;
return ((ULONG)kickmemory[addr >> 1] << 16) | kickmemory[(addr >> 1)+1];
}
UWORD kickmem_wget(CPTR addr)
{
addr -= kickmem_start & (kickmem_size-1);
addr &= kickmem_size-1;
return kickmemory[addr >> 1];
}
UBYTE kickmem_bget(CPTR addr)
{
addr -= kickmem_start & (kickmem_size-1);
addr &= kickmem_size-1;
return kickmemory[addr >> 1] >> (addr & 1 ? 0 : 8);
}
void kickmem_lput(CPTR a, ULONG b)
{
}
void kickmem_wput(CPTR a, UWORD b)
{
}
void kickmem_bput(CPTR a, UBYTE b)
{
}
bool kickmem_check(CPTR addr, ULONG size)
{
addr -= kickmem_start & (kickmem_size-1);
addr &= kickmem_size-1;
return (addr + size) < kickmem_size;
}
UWORD *kickmem_xlate(CPTR addr)
{
addr -= kickmem_start & (kickmem_size-1);
addr &= kickmem_size-1;
return kickmemory + (addr >> 1);
}
static bool load_kickstart(void)
{
int i;
ULONG cksum = 0, prevck = 0;
unsigned char buffer[8];
FILE *f = fopen("kick.rom", "rb");
if (f == NULL) {
fprintf(stderr, "No Kickstart ROM found.\n");
return false;
}
fread(buffer, 1, 8, f);
if (buffer[4] == 0 && buffer[5] == 8 && buffer[6] == 0 && buffer[7] == 0) {
fprintf(stderr, "You seem to have a ZKick file there... You probably lose.\n");
zkickfile = 1;
} else
fseek(f, 0, SEEK_SET);
for(i = 0; i < kickmem_size/2; i++) {
if (fread(buffer, 1, 2, f) < 2) {
if (feof(f) && i == kickmem_size/4) {
fprintf(stderr, "Warning: Kickstart is only 256K.\n");
memcpy (kickmemory + kickmem_size/4, kickmemory, kickmem_size/2);
break;
} else {
fprintf(stderr, "Error while reading Kickstart.\n");
return false;
}
}
kickmemory[i] = buffer[0]*256 + buffer[1];
}
fclose (f);
for (i = 0; i < kickmem_size/4; i++) {
ULONG data = kickmemory[i*2]*65536 + kickmemory[i*2+1];
cksum += data;
if (cksum < prevck)
cksum++;
prevck = cksum;
}
if (cksum != 0xFFFFFFFF) {
fprintf(stderr, "Warning: Kickstart checksum incorrect. You probably have a corrupted ROM image.\n");
}
return true;
}
/* Address banks */
addrbank chipmem_bank = {
chipmem_lget, chipmem_wget, chipmem_bget,
chipmem_lput, chipmem_wput, chipmem_bput,
chipmem_xlate, chipmem_check
};
addrbank bogomem_bank = {
bogomem_lget, bogomem_wget, bogomem_bget,
bogomem_lput, bogomem_wput, bogomem_bput,
bogomem_xlate, bogomem_check
};
addrbank kickmem_bank = {
kickmem_lget, kickmem_wget, kickmem_bget,
kickmem_lput, kickmem_wput, kickmem_bput,
kickmem_xlate, kickmem_check
};
void memory_init(void)
{
buserr = false;
map_banks(chipmem_bank, 0, 256);
map_banks(custom_bank, 0xC0, 0x20);
map_banks(cia_bank, 0xBF, 1);
map_banks(clock_bank, 0xDC, 1);
if (use_slow_mem && bogomem_size > 0) {
bogomemory = (UWORD *)malloc (bogomem_size);
map_banks(bogomem_bank, 0xC0, bogomem_size >> 16);
}
map_banks(rtarea_bank, 0xF0, 1);
rtarea_init ();
if (!load_kickstart()) {
init_ersatz_rom(kickmemory);
}
if (zkickfile)
map_banks(kickmem_bank, 0x20, 8);
map_banks(kickmem_bank, 0xF8, 8);
if (use_fast_mem && fastmem_size > 0 && !zkickfile) {
map_banks(expamem_bank, 0xE8, 1);
expamem_init();
}
}
void map_banks(addrbank bank, int start, int size)
{
int bnr;
for(bnr=start; bnr < start+size; bnr++) {
do_lget[bnr] = bank.lget;
do_wget[bnr] = bank.wget;
do_bget[bnr] = bank.bget;
do_lput[bnr] = bank.lput;
do_wput[bnr] = bank.wput;
do_bput[bnr] = bank.bput;
do_xlateaddr[bnr] = bank.xlateaddr;
do_check[bnr] = bank.check;
}
}